package com.zapi.form.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.zapi.constants.DataBaseConstans;
import com.zapi.form.mapper.FormDataMapper;
import com.zapi.form.model.dto.*;
import com.zapi.form.model.entity.FormTableInfo;
import com.zapi.form.model.vo.BusinessDataPageVO;
import com.zapi.form.service.FormColumnInfoService;
import com.zapi.form.service.FormDataService;
import com.zapi.form.service.FormTableInfoService;
import com.zapi.workflow.service.model.dto.StartProcessDTO;
import com.zapi.workflow.service.model.entity.WfProcessInstance;
import com.zapi.workflow.service.service.WfProcessInstanceService;
import com.zapi.workflow.service.model.dto.StartProcessDTO;
import com.zapi.workflow.service.model.entity.WfProcessDefinition;
import com.zapi.workflow.service.model.entity.WfProcessInstance;
import com.zapi.workflow.service.service.WfProcessDefinitionService;
import com.zapi.workflow.service.service.WfProcessInstanceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 业务数据通用服务实现
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class FormDataServiceImpl implements FormDataService {

	@Autowired
	private  FormTableInfoService formTableInfoService;
	@Autowired
	private FormDataMapper formDataMapper;
	@Autowired
	private  FormColumnInfoService formColumnInfoService;

	@Autowired
	private FormServiceImpl formService;

	@Autowired
	private WfProcessDefinitionService wfProcessDefinitionService;

	/**
	 * 流程实例服务
	 * 负责流程运行时的管理
	 */
	@Autowired
	private WfProcessInstanceService processInstanceService;


	private String resolveBusinessTableName(String formId) {
		FormTableInfo tableInfo = formTableInfoService.getByFormId(formId);
		if (tableInfo == null) {
			throw new IllegalArgumentException("表单未配置业务表: formId=" + formId);
		}
		return DataBaseConstans.BUSINESS_PREFIX + tableInfo.getTableName();
	}

	private List<Map<String, Object>> asEntries(Map<String, Object> data) {
		if (data == null || data.isEmpty()) {
			return Collections.emptyList();
		}
		// MyBatis 中遍历 Map 时顺序不保证，这里直接传 Map 列表即可
		return Collections.singletonList(data);
	}

	private List<Map<String, Object>> criteriaEntries(Map<String, Object> criteria) {
		if (criteria == null) {
			return Collections.emptyList();
		}
		return criteria.entrySet().stream()
			.map(e -> {
				Map<String, Object> m = new HashMap<>(2);
				m.put("key", e.getKey());
				m.put("value", e.getValue());
				return m;
			}).collect(Collectors.toList());
	}

	/**
	 * 安全获取操作用户名
	 * - 优先获取当前登录用户的姓名
	 * - 在开放接口/匿名请求中，UserSession 可能不存在或抛异常
	 * - 此方法兜底返回 "external_api"，保证审计字段永不为空
	 */
	private String resolveOperatorUsername() {
		try {
			// 运行时尝试通过反射调用 Sa-Token 的 StpUtil（若存在则使用其登录ID）
			try {
				Class<?> stpClass = Class.forName("cn.dev33.satoken.stp.StpUtil");
				boolean isLogin = (boolean) stpClass.getMethod("isLogin").invoke(null);
				if (isLogin) {
					Object loginId = stpClass.getMethod("getLoginIdAsString").invoke(null);
					if (loginId != null) {
						return String.valueOf(loginId);
					}
				}
			} catch (ClassNotFoundException ignore) {
				// 未引入 Sa-Token，忽略
			} catch (Throwable t) {
				log.debug("反射调用 StpUtil 失败: {}", t.getMessage());
			}
		} catch (Exception e) {
			log.warn("获取当前登录用户失败: {}", e.getMessage());
		}
		return "external_api";
	}
	


	@Override
	public Long insert(String formId, Map<String, Object> data) {
		String tableName = resolveBusinessTableName(formId);
		// 设置创建时间和创建人（未登录时默认 external_api）
		if (data != null) {
			data.put("is_deleted", 0);
			data.put("create_time", LocalDateTime.now());
			data.put("create_user", resolveOperatorUsername());
		}
		formDataMapper.insertDynamic(tableName, asEntries(data));
		// 这里返回主键，若为自增主键需再查，或在 data 中已含 id 则返回
		Object id = data != null ? data.get("id") : null;
		return id instanceof Number ? ((Number) id).longValue() : null;
	}

	@Override
	public boolean updateById(String formId, Long id, Map<String, Object> data) {
		String tableName = resolveBusinessTableName(formId);
		// 设置修改时间和修改人（未登录时默认 external_api）
		if (data != null) {
			data.put("update_time", LocalDateTime.now());
			data.put("update_user", resolveOperatorUsername());
		}
		return formDataMapper.updateByIdDynamic(tableName, id, asEntries(data)) > 0;
	}

	// 旧的 AND-only 方法已移除，统一走 DNF 版本

	/**
	 * 新增：按 DNF 条件更新（OR 的多个 AND 组合）
	 */
	@Override
	public boolean updateByCriteriaGroups(String formId, List<Map<String, Object>> criteriaList, Map<String, Object> data) {
		String tableName = resolveBusinessTableName(formId);
		if (data != null) {
			data.put("update_time", LocalDateTime.now());
			data.put("update_user", resolveOperatorUsername());
		}
		// 将 List<Map> 转换为 MyBatis 需要的 List<List<Map>>（每个 Map 表示 AND 组）
		List<List<Map<String, Object>>> groups = new ArrayList<>();
		if (criteriaList != null) {
			for (Map<String, Object> m : criteriaList) {
				groups.add(criteriaEntries(m));
			}
		}
		return formDataMapper.updateByCriteriaGroupsDynamic(tableName, groups, asEntries(data)) > 0;
	}

	/**
	 * 新增：按 DNF 条件删除（OR 的多个 AND 组合）
	 */
	@Override
	public boolean deleteByCriteriaGroups(String formId, List<Map<String, Object>> criteriaList) {
		String tableName = resolveBusinessTableName(formId);
		// 将 List<Map> 转换为 MyBatis 需要的 List<List<Map>>（每个 Map 表示 AND 组）
		List<List<Map<String, Object>>> groups = new ArrayList<>();
		if (criteriaList != null) {
			for (Map<String, Object> m : criteriaList) {
				groups.add(criteriaEntries(m));
			}
		}
		return formDataMapper.deleteByCriteriaGroupsDynamic(tableName, groups) > 0;
	}

	@Override
	public Map<String, Object> getById(String formId, Long id) {
		String tableName = resolveBusinessTableName(formId);
		return formDataMapper.selectByIdDynamic(tableName, id);
	}

	@Override
	public boolean deleteById(String formId, Long id) {
		String tableName = resolveBusinessTableName(formId);
		// 逻辑删除前先更新审计字段（未登录时默认 external_api）
		Map<String, Object> deleteData = new HashMap<>();
		deleteData.put("update_time", LocalDateTime.now());
		deleteData.put("update_user", resolveOperatorUsername());
		// 先更新审计字段，再执行逻辑删除
		formDataMapper.updateByIdDynamic(tableName, id, asEntries(deleteData));
		return formDataMapper.deleteByIdDynamic(tableName, id) > 0;
	}

	@Override
	public Page<Map<String, Object>> page(String formId, Map<String, Object> criteria, int pageNo, int pageSize) {
		String tableName = resolveBusinessTableName(formId);
		int offset = Math.max(pageNo - 1, 0) * pageSize;
		List<Map<String, Object>> records = formDataMapper.pageQueryDynamic(tableName, criteriaEntries(criteria), offset, pageSize);
		Long count = formDataMapper.countQueryDynamic(tableName, criteriaEntries(criteria));
		Page<Map<String, Object>> page = new Page<>(pageNo, pageSize);
		page.setTotal(count == null ? 0 : count);
		page.setRecords(records);
		return page;
	}

	@Override
	public boolean deleteBatch(String formId, List<Long> ids) {
		String tableName = resolveBusinessTableName(formId);
		return formDataMapper.batchDeleteByIds(tableName, ids) > 0;
	}

	// ==================== 新增的业务方法实现 ====================

	@Override
	public BusinessDataPageVO pageBusinessData(BusinessDataPageDTO dto) {
		// 走已有的通用分页实现
		Page<Map<String, Object>> page = page(dto.getFormId(), dto.getCriteria(), dto.getPageNo(), dto.getPageSize());
		BusinessDataPageVO result = new BusinessDataPageVO();
		result.setRecords(page.getRecords());
		result.setTotal(page.getTotal());
		result.setColumns(buildTableColumns(dto.getFormId()));
		result.setPageNo((long) dto.getPageNo());
		result.setPageSize((long) dto.getPageSize());
		return result;
	}

	@Override
	public Map<String, Object> getBusinessDataById(BusinessDataGetDTO dto) {
		return getById(dto.getFormId(), dto.getId());
	}

	@Override
	public Long createBusinessData(BusinessDataCreateDTO dto) throws Exception {
		Map<String, Object> data = dto.getData();
		// 数据新增，需要手动添加ID、逻辑删除字段和审计字段
		if (data != null) {
			if (ObjectUtil.isEmpty(data.get("id"))) {
				data.put("id", IdWorker.getId());
			}
			data.put("is_deleted", 0);
			data.put("create_time", LocalDateTime.now());
			data.put("create_user", resolveOperatorUsername());
		}

		Long id = insert(dto.getFormId(), data);


		/***
		 * 发起工作流
		 */

		/***
		 * 查询wf_process_definition流程定义表中
		 * business_type 业务类型：1-系统表单 2-业务表单
		 * business_type === 1
		 * 系统表单标识（系统表单类型时使用）
		 * system_form_key === “zapi_flow_test_order”
		 *
		 * id就是  fadd85b65bc31cd01fe0352442176d63
		 */
		WfProcessDefinition info =wfProcessDefinitionService.getByBusinessTypeAndForm(2,null,dto.getFormId(),1);
		if (ObjectUtil.isEmpty(info)) {
			return id;
		}else{
			StartProcessDTO startProcessDTO=new StartProcessDTO();
			startProcessDTO.setProcessDefinitionId(info.getId());
			/// 业务数据ID
			startProcessDTO.setBusinessKey(id.toString());
			/// 启动流程用户ID，取当前用户ID
			startProcessDTO.setStartUser("1");
			Map<String, Object> dataFlow = dto.getData();
			dataFlow.put("id", id.toString());
			startProcessDTO.setVariables(dataFlow);
			log.info("发起工作流请求参数："+ JSONObject.toJSONString(startProcessDTO));
			WfProcessInstance result = processInstanceService.startProcess(startProcessDTO);
			log.info("发起工作流结束："+ JSONObject.toJSONString(result));
		}
		return id;
	}

	@Override
	public boolean updateBusinessData(BusinessDataUpdateDTO dto) {
		Map<String, Object> data = dto.getData();
		// 设置修改时间和修改人（未登录时默认 external_api）
		if (data != null) {
			data.put("update_time", LocalDateTime.now());
			data.put("update_user", resolveOperatorUsername());
		}
		return updateById(dto.getFormId(), dto.getId(), data);
	}

	@Override
	public boolean deleteBusinessData(BusinessDataDeleteDTO dto) {
		return deleteById(dto.getFormId(), dto.getId());
	}

	@Override
	public boolean batchDeleteBusinessData(BusinessDataBatchDeleteDTO dto) {
		return deleteBatch(dto.getFormId(), dto.getIds());
	}

	@Override
	public Map<String, Object> getTableInfoByFormId(String formId) {
		String tableName = resolveBusinessTableName(formId);
		FormTableInfo tableInfo = formTableInfoService.getByFormId(formId);
		Map<String, Object> result = new HashMap<>();
		result.put("formConfig",formService.getFormDetail(formId).getFormConfig());
		result.put("tableInfo", tableInfo);
		result.put("columnInfos", formColumnInfoService.listByFormId(formId));
		return result;
	}

	/**
	 * 构建表格列（返回 {label, prop}，label 优先中文注释）
	 */
	private List<Map<String, String>> buildTableColumns(String formId) {
		return formColumnInfoService.listByFormId(formId).stream()
			.map(col -> {
				String prop = col.getColumnName();
				String label = (col.getColumnComment() == null || col.getColumnComment().trim().isEmpty())
					? prop
					: col.getColumnComment();
				Map<String, String> m = new HashMap<>(2);
				m.put("label", label);
				m.put("prop", prop);
				return m;
			})
			.collect(Collectors.toList());
	}
} 